/**
 * FileName: CheckGPSTimer
 * Author:   Leopold
 * Date:     2018/10/4 17:12
 * Description:
 * History:
 */
package cn.mcsys.viewer.core.service.timer;

import cn.mcsys.myadmin.common.config.LoadRidePointConfiguration;
import cn.mcsys.myadmin.common.config.LoadSpecialLineConfiguration;
import cn.mcsys.myadmin.common.utils.DateUtils;
import cn.mcsys.myadmin.common.utils.MapUtils;
import cn.mcsys.myadmin.dubbo.service.BackService;
import cn.mcsys.myadmin.modules.air.entity.AirCar;
import cn.mcsys.myadmin.common.utils.GpsUtils;
import cn.mcsys.myadmin.modules.air.entity.AirCarRecord;
import org.springframework.beans.factory.annotation.Autowired;

import java.awt.geom.Point2D;
import java.util.*;


public class CheckGPSTimer {

    static Map<Integer, AirCar> base = new HashMap<>();
    static Map<Integer, Integer> count = new HashMap<>();

    @Autowired
    private BackService backService;


    public void checkGps() {
        List<AirCar> cars = backService.selectZHAllCarList();
        for (AirCar car : cars) {
            if (car.getLon() != null && car.getLat() != null) {
                carInWhere(car);
            }
        }
    }

    public void checkCarStatus() {
        List<AirCar> cars = backService.selectZHAllCarList();
        for (AirCar car : cars) {
            if (car.getLon() != null && car.getLat() != null) {
                double seconds = DateUtils.getDistanceSecondsOfTwoDate(car.getModificationDate(), new Date());
                if (seconds >= 300) {
                    //超过5分钟无数据，设置该车异常
                    if (car.getStatus() != null) {
                        setExceptionCar(car);
                    }
                } else {
                    //设置车辆状态
                    setCarStatus(car);
                }
            }
        }
    }

    private void setCarStatus(AirCar car) {
        AirCarRecord record = backService.selectLatestCarRecord(car, null);
        if (car.getStatus() == null) {
            AirCar airCar = base.get(car.getId());
            if (airCar != null) {
                //在航展馆内
                if (inAirShowHall(airCar)) {
                    if(record.getStatus()!=AirCar.ARRIVE) {
                        car.setStatus(AirCar.ARRIVE);
                        backService.insertCarRecord(car, car.getStatus());
                        backService.updateCarStatus(car.getId().longValue(), car.getStatus());
                        count.put(car.getId(), 0);
                    }
                } else if (isInRidePoint(airCar)) {
                    if(record.getStatus()!=AirCar.WAITSTART) {
                        car.setStatus(AirCar.WAITSTART);
                        backService.insertCarRecord(car, car.getStatus());
                        backService.updateCarStatus(car.getId().longValue(), car.getStatus());
                        count.put(car.getId(), 0);
                    }
                } else {
                    //判断距离 比上次近了返回 1 比上次远 返回 -1 其余情况返回 0
                    Integer gap = getGap(airCar, car);
                    //计数君 计算近/远次数
                    Integer car_counter = count.get(airCar.getId());
                    if (car_counter == null) {
                        car_counter = 0;
                    }
                    count.put(airCar.getId(), car_counter + gap);
                    //计数君 突破后 设置状态
                    if (car_counter + gap > 2) {
                        if(record.getStatus()!=AirCar.RIDING) {
                            car.setStatus(AirCar.RIDING);
                            backService.insertCarRecord(car, car.getStatus());
                            count.put(car.getId(), 0);
                        }
                    } else if (car_counter + gap < -2) {
                        if(record.getStatus()!=AirCar.RETURNED) {
                            car.setStatus(AirCar.RETURNED);
                            backService.insertCarRecord(car, car.getStatus());
                            count.put(car.getId(), 0);
                        }
                    }
                }
            }
            base.put(car.getId(), car);
        }else{
            carInWhere(car);
        }
    }

    private boolean isInRidePoint(AirCar car) {
        String note = car.getAirRidePoint().getNote();
        Double lon = Double.valueOf(car.getLon());
        Double lat = Double.valueOf(car.getLat());
//        gps转高德坐标系(gcj02)
        GpsUtils gpsUtils = GpsUtils.gps84_To_Gcj02(lat, lon);
        lat = gpsUtils.getMgLat();
        lon = gpsUtils.getMgLon();
        List<Point2D.Double> pointList = LoadRidePointConfiguration.getPointList(note);
        if (MapUtils.IsPtInPoly(new Point2D.Double(lon, lat), pointList)) {
            return true;
        }
        return false;
    }

    private boolean inAirShowHall(AirCar car) {
        Double lon = Double.valueOf(car.getLon());
        Double lat = Double.valueOf(car.getLat());
//        gps转高德坐标系(gcj02)
        GpsUtils gpsUtils = GpsUtils.gps84_To_Gcj02(lat, lon);
        lat = gpsUtils.getMgLat();
        lon = gpsUtils.getMgLon();
        List<Point2D.Double> doubleList = LoadRidePointConfiguration.hangzhanguan.get(LoadRidePointConfiguration.HANGZHANGUAN);
        if (MapUtils.IsPtInPoly(new Point2D.Double(lon, lat), doubleList)) {
            return true;
        }
        return false;
    }

    private void setExceptionCar(AirCar car) {
        base.put(car.getId(), car);
        count.put(car.getId(), 0);
        backService.clearCarStatus(car.getId());
    }

    /**
     * 判断当前车辆处在什么状态下
     *
     * @param car
     */
    private void carInWhere(AirCar car) {
//        判断是否在乘车点
//        判断是否在线路中
//        判断是否在航展馆
        Double lon = Double.valueOf(car.getLon());
        Double lat = Double.valueOf(car.getLat());
//        gps转高德坐标系(gcj02)
        GpsUtils gpsUtils = GpsUtils.gps84_To_Gcj02(lat, lon);
        lat = gpsUtils.getMgLat();
        lon = gpsUtils.getMgLon();
//        当前时间戳
        long currentTimeMillis = System.currentTimeMillis();
//        如果都不在则视为偏移线路
//      判断是否在展馆中
//        判断当前的车辆是否在线上
        Integer online = car.getIsOnline();
        Integer isOnline = null;
        if ((isOnline = inAirShowHall(car, lon, lat, currentTimeMillis)) == -1) {
//           判断是否在乘车点上
            System.out.println("不在航展馆中");
            if ((isOnline = isInRidePoint(car, lon, lat, currentTimeMillis)) == -1) {
                System.out.println("不在乘车点中");
//              如果不在线路上
                if ((isOnline = isInLine(car, lon, lat, currentTimeMillis)) == -1) {
                    System.out.println("不在线路中");
//                  设置车辆为偏移线路状态
                    car.setIsOnline(-1);
                }
            }
        }
        if (isOnline == 0) {
            car.setIsOnline(0);
        }
//        设置在线路中(添加偏移线路状态字段,上下班字段)
        if (isOnline != online) {
            backService.updateIsOnLine(car.getId(), car.getIsOnline());
        }
    }

    /**
     * 判断是否在航展展馆
     *
     * @param car
     * @param lon
     * @param lat
     * @param currentTimeMillis
     */
    private Integer inAirShowHall(AirCar car, Double lon, Double lat, long currentTimeMillis) {
        List<Point2D.Double> doubleList = LoadRidePointConfiguration.hangzhanguan.get(LoadRidePointConfiguration.HANGZHANGUAN);
        if (MapUtils.IsPtInPoly(new Point2D.Double(lon, lat), doubleList)) {
            if (car.getStatus() == AirCar.RIDING) {
                car.setStatus(AirCar.ARRIVE);
//          新增车辆状态表信息
                backService.insertCarRecord(car, car.getStatus());
                backService.updateCarStatus(car.getId().longValue(), car.getStatus());
            }
            return 0;
        }
        return -1;
    }

    /**
     * 判断是否在乘车点上
     *
     * @param car
     * @param lon
     * @param lat
     * @param currentTimeMillis
     */
    private Integer isInRidePoint(AirCar car, Double lon, Double lat, long currentTimeMillis) {
        String note = car.getAirRidePoint().getNote();
//        找到该车辆对应的乘车点
        Integer isOnline = -1;
        if (note != null) {
            List<Point2D.Double> pointList = LoadRidePointConfiguration.getPointList(note);
            if (MapUtils.IsPtInPoly(new Point2D.Double(lon, lat), pointList)) {
                AirCarRecord airCarRecord = backService.selectLatestCarRecord(car, AirCar.WAITSTART);
                if (car.getStatus() == AirCar.RETURNED) {
//          只要进入乘车点中,就设置为待发车状态
                    car.setStatus(AirCar.WAITSTART);
//                        新增车辆状态表信息
                    backService.insertCarRecord(car, car.getStatus());
//            更新车辆状态
                    backService.updateCarStatus(car.getId().longValue(), car.getStatus());
                }
                isOnline = 0;
            }
        }
        return isOnline;
    }

    /**
     * 判断是否在线路上,一辆车只能存在一个状态中
     *
     * @param car
     * @param lon
     * @param lat
     * @param currentTimeMillis
     * @return
     */
    private Integer isInLine(AirCar car, Double lon, Double lat, long currentTimeMillis) {
        Set<Map.Entry<String, List<Point2D.Double>>> entries = LoadSpecialLineConfiguration.lineMap.entrySet();
        Integer isOnline = -1;
        for (Map.Entry<String, List<Point2D.Double>> entry : entries) {
            if (isOnline == 0) {
                break;
            }
//          判断是否线路中
            if (MapUtils.IsPtInPoly(new Point2D.Double(lon, lat), entry.getValue())) {
                if (car.getStatus() == AirCar.WAITSTART) {
                    car.setStatus(AirCar.RIDING);
//                        新增车辆状态表信息
                    backService.insertCarRecord(car, car.getStatus());
//                        新增实时发车表信息
                    backService.autoInsertRealTimeMessage(car, AirCar.RIDING);
                } else if (car.getStatus() == AirCar.ARRIVE) {
                    car.setStatus(AirCar.RETURNED);
                    backService.insertCarRecord(car, car.getStatus());
                }
                isOnline = 0;
            }
        }
        if (isOnline == 0) {
            backService.updateCarStatus(car.getId().longValue(), car.getStatus());
        }
        return isOnline;
    }

    private Integer getGap(AirCar airCar, AirCar car) {
        double a = Math.abs(Double.parseDouble(airCar.getLon()) - 113.387456) + Math.abs(Double.parseDouble(airCar.getLat()) - 22.016784);
        double b = Math.abs(Double.parseDouble(car.getLon()) - 113.387456) + Math.abs(Double.parseDouble(car.getLat()) - 22.016784);
        if (a > b) {
            return 1;
        }
        if (a < b) {
            return -1;
        }
        return 0;
    }

//         乘车点中
//                if (DateUtils.isInDate(currentTimeMillis, "07:00:00", "12:00:00")) {
//        if (car.getStatus() == AirCar.GO_RIDEPOINT) {
//            car.setStatus(AirCar.WAITSTART);
////                        新增车辆状态表信息
//            backService.insertCarRecord(car, AirCar.WAITSTART);
//        } else if (car.getStatus() == AirCar.ARRIVE) {
//            car.setStatus(AirCar.AGAINSTART);
////                        更改车辆状态信息
//            backService.insertCarRecord(car, AirCar.AGAINSTART);
//        }
//    } else if (DateUtils.isInDate(currentTimeMillis, "13:00:00", "18:00:00")) {
//        if (car.getStatus() == AirCar.RETURNING) {
//            car.setStatus(AirCar.RETURNED);
//        }
//    }

//          线路中
    //                判断是否处于待发车和7-12点中
//                if (car.getStatus() == AirCar.WAITSTART) {
//        car.setStatus(AirCar.RIDING);
////                        新增车辆状态表信息
//        backService.insertCarRecord(car, AirCar.RIDING);
////                        新增实时发车表信息
//        backService.autoInsertRealTimeMessage(car, AirCar.RIDING);
//    } else if (car.getStatus() == AirCar.ARRIVE) {
//        car.setStatus(AirCar.AGAINSTART);
////                        更改车辆状态信息
//        backService.insertCarRecord(car, AirCar.AGAINSTART);
//    }
//                if (car.getStatus() == AirCar.ARRIVE) {
//        car.setStatus(AirCar.RETURNING);
//    } else if (car.getStatus() == AirCar.RETURNED) {
//        car.setStatus(AirCar.AGAINRETURN);
//    }
//    isOnline = 0;
//}
}
